/*=============================================================================
*
*   Copyright (C) 2020 All rights reserved.
*
*   Filename:		time_function_interface.hpp
*
*   Author: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Date: 2020-02-24 22:53
*
*   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Last modified:	2020-03-23 15:22
*
*   Description:
*
=============================================================================*/
#ifndef ITIMEFUNCTION_H
#define ITIMEFUNCTION_H

#include "../../types.hpp"
#include "../../util/factory.hpp"
#include <boost/property_tree/ptree.hpp>

namespace geoxfem {
namespace arithmetic {

struct Time_Function_Interface {
  using ptree   = boost::property_tree::ptree;
  using factory = dp14::
    factory<Time_Function_Interface, const ptree&, const _real&, const _real&>;

  Time_Function_Interface();
  Time_Function_Interface(const ptree& data, const _real& t0, const _real& t1);
  virtual ~Time_Function_Interface();

  static Time_Function_Interface::factory& getFactory() {
    return Time_Function_Interface::factory::instance();
  }

  /** return value of function at given time step
   *
   * @param _curr_time
   * @return
   */
  virtual _real getValueAt(const _real& _curr_time) const = 0;

  /** return slope of function at given time step
   *
   * @param _start_time
   * @param _end_time   :
   * @return
   */
  _real getIncrementBetween(const _real& _start_time,
                            const _real& _end_time) const;

  /** return acceleration of function at given time step
   *
   * @param _curr_time
   * @return
   */
  _real getSlopeAt(const _real& _curr_time) const;

protected:
  ptree m_data;
  _real m_t0;
  _real m_t1;
};

Time_Function_Interface::Time_Function_Interface() = default;

Time_Function_Interface::Time_Function_Interface(const ptree& data,
                                                 const _real& t0,
                                                 const _real& t1)
    : m_data{data}, m_t0{t0}, m_t1{t1} {}

Time_Function_Interface::~Time_Function_Interface() = default;

_real Time_Function_Interface::getIncrementBetween(/*{{{*/
                                                   const _real& _start_time,
                                                   const _real& _end_time)
  const {
  return getValueAt(_end_time) - getValueAt(_start_time);
} /*}}}*/

_real Time_Function_Interface::getSlopeAt(
  const _real& _curr_time) const { /*{{{*/
  _real dt = _curr_time * _real(1e-5);
  dt       = dt > _real(1e-3) ? dt : _real(1e-3);
  return (getValueAt(_curr_time + dt) - getValueAt(_curr_time - dt)) / r2 / dt;
} /*}}}*/

}  // namespace arithmetic
}  // namespace geoxfem

#endif /* ITIMEFUNCTION_H */
